package casts.home
{
   import boy.progression.*;
   
   import com.greensock.BlitMask;
   import com.greensock.TweenMax;
   import com.greensock.easing.Linear;
   import com.greensock.events.LoaderEvent;
   import com.greensock.loading.ImageLoader;
   import com.greensock.loading.LoaderMax;
   
   import flash.display.Bitmap;
   import flash.display.BitmapData;
   import flash.display.BlendMode;
   import flash.display.DisplayObject;
   import flash.display.MovieClip;
   import flash.display.Sprite;
   import flash.events.Event;
   import flash.geom.Matrix;
   
   import jp.progression.casts.CastMovieClip;
   
   /**
    * @author cjboy1984@gmail.com
    */
   public class RetroTV_Slideshow extends CastMovieClip
   {
      // fla
      public var mcSnapshot:MovieClip;
      
      // tv simulation (screen dot)
      //      private var tv_effx:Sprite = new Sprite();
      private var tv_effx:RetroTV;
      
      // slideshow
      private var picture_container:Sprite = new Sprite(); // all of the pictures are added into it, cause I need to make a tv effect. :P
      private var pno:int; // slideshow index
      private var playing:Boolean; // is slideshow activated
      private const PICTURE_WIDTH:Number = 750;
      private const PICTURE_HEIGHT:Number = 405;
      private var picture_urls:Vector.<String> = Vector.<String>([
         'image/bg_1.jpg',
         'image/bg_2.jpg',
         'image/bg_3.jpg',
         'image/bg_4.jpg',
         'image/bg_5.jpg',
         'image/bg_6.jpg'
      ]);
      private var pictures:Vector.<DisplayObject>; // all the pictures
      private var pictures_blitmsk:Vector.<BlitMask>; // all the blit-msk of the pictures
      private var picture_loader:LoaderMax;
      // canvas, very necessary
      private var canvas:Bitmap;
      
      public function RetroTV_Slideshow(initObject:Object = null)
      {
         blendMode = BlendMode.LAYER;
         
         super(initObject);
         
         id = 'home_slideshow_bg';
         group = 'home';
         
         stop();
      }
      
      // --------------------- LINE ---------------------
      
      // ################### protected ##################
      
      override protected function atCastAdded():void
      {
         alpha = 1;
         scaleX = scaleY = 1;
         
         init();
         
         // basic
         onStageResize();
         stage.addEventListener(Event.RESIZE, onStageResize);
      }
      
      override protected function atCastRemoved():void
      {
         // basic
         if (stage) stage.removeEventListener(Event.RESIZE, onStageResize);
         
         destroy();
         
         addCommand(
            new DoTweenMax(this, 0.7, { scaleX:1.3, scaleY:1.3, alpha:0 } )
         );
      }
      
      // #################### private ###################
      
      private function init():void
      {
         // picture container, it contains all the pictures and then drawed by the "canvas"
         picture_container.blendMode = BlendMode.LAYER;
         picture_container.cacheAsBitmap = true;
         // add the default picture into it
         picture_container.addChild(mcSnapshot);
         
         // retro effx
         createTV_Effx();
         
         // [ slide show ]
         // initialize the 1st one, mcSnapshot
         playing = false;
         pictures = new Vector.<DisplayObject>();
         pictures.push(mcSnapshot);
         if (pictures && pictures.length >= 2) // if once loaded
         {
            trace('home | startSlideshow directly');
            startSlideshow();
         }
         else
         {
            trace('home | loadPictures');
            loadPictures();
         }
      }
      
      private function destroy():void
      {
         // slideshow
         stopSlideshow();
         stopLoadPicture();
         
         // tv effx
         destroyTV_Effx();
      }
      
      // ________________________________________________
      //                                     Load Picture
      
      private function loadPictures():void
      {
         picture_loader = new LoaderMax();
         for (var i:int = 0; i < picture_urls.length; ++i) 
         {
            var ldr:ImageLoader = new ImageLoader(picture_urls[i], { 
               container:picture_container, // assign the parent as picture_container
               centerRegistration:true,
               alpha:0
            } );
            // complete handler
            ldr.addEventListener(LoaderEvent.COMPLETE, onLoaded);
            
            picture_loader.append(ldr);
         }
         picture_loader.maxConnections = 2;
         picture_loader.load();
      }
      
      private function stopLoadPicture():void
      {
         // I want to let the connections keep going :P
      }
      
      // each ImageLoader complete handler
      private function onLoaded(e:LoaderEvent = null):void
      {
         var ldr:ImageLoader = ImageLoader(e.target);
         ldr.removeEventListener(LoaderEvent.COMPLETE, onLoaded);
         
         // save the content
         pictures.push(ldr.content);
         
         if (!playing && stage) 
         {
            startSlideshow();
         }
      }
      
      // ________________________________________________
      //                                        Slideshow
      
      private function startSlideshow():void
      {
         trace('home | startSlideshow');
         playing = true;
         
         // resize handler
         stage.addEventListener(Event.RESIZE, resizeAllPictures);
         
         // init
         pno = 0;
         
         // start without blitmask
         TweenMax.to(pictures[pno], 4, { width:'+50', height:'+50', ease:Linear.easeNone, onComplete:showNextPicture } );
      }
      
      private function stopSlideshow():void
      {
         trace('home | stopSlideshow');
         playing = false;
         
         // target
         for (var i:int = 0; i < pictures.length; ++i) 
         {
            var mc:DisplayObject = pictures[i];
            TweenMax.killTweensOf(mc);
         }
         
         // resize handler
         stage.removeEventListener(Event.RESIZE, resizeAllPictures);
      }
      
      private function showNextPicture():void
      {
         if (++pno >= pictures.length) pno = 0;
         
         trace('home | showNextPicture =', pno);
         
         // target
         var now_mc:DisplayObject = pictures[pno];
         now_mc.alpha = 0;
         now_mc.scaleX = now_mc.scaleY = 1;
         now_mc.parent.setChildIndex(now_mc, now_mc.parent.numChildren - 1);
         
         // start without blitmask
         TweenMax.to(now_mc, 1, { alpha:1 } );
         TweenMax.to(now_mc, 4, { width:'+50', height:'+50', ease:Linear.easeNone, onComplete:showNextPicture } );
      }
      
      // ________________________________________________
      //                                          TV Effx
      
      private function createTV_Effx():void
      {
         // canvas
         canvas = null; // clear old data
         canvas = new Bitmap();
         // test, let you see the canvas working...
         //         addChildAt(canvas, numChildren - 1);
         
         // clear old RetroTV
         if (tv_effx && contains(tv_effx)) 
         {
            removeChild(tv_effx);
            tv_effx = null;
         }
         // Generally, the width and the height of the television effect will be, respectively:
         // 3 x phosphorWidth x sceneWidth
         // 3 x phosphorHeight x sceneHeight
         tv_effx = new RetroTV(source_width, source_height, 1);
         tv_effx.warping = false;
         tv_effx.noiseAmount = 0;
         tv_effx.redOffsetX = 0;
         tv_effx.redOffsetY = 0;
         tv_effx.greenOffsetX = 0;
         tv_effx.greenOffsetY = 0;
         tv_effx.blueOffsetX = 0;
         tv_effx.blueOffsetY = 0;
         tv_effx.x = -tv_effx.width / 2;
         tv_effx.y = -tv_effx.height / 2;
         // so tv_effx will take the "canvas" as the source
         tv_effx.scene.addChild(canvas);
         
         // add effect onto stage
         addChildAt(tv_effx, numChildren - 1);
         tv_effx.addEventListener(Event.ENTER_FRAME, updateTV_Effx);
      }
      
      private function destroyTV_Effx():void
      {
         if (tv_effx) 
         {
            tv_effx.removeEventListener(Event.ENTER_FRAME, updateTV_Effx);
         }
      }
      
      private function updateTV_Effx(e:Event):void
      {
         var matrix:Matrix = new Matrix();
         matrix.translate(PICTURE_WIDTH / 2, PICTURE_HEIGHT / 2);
         matrix.scale(source_width / PICTURE_WIDTH, source_height / PICTURE_HEIGHT);
         // draw the canvas
         canvas.bitmapData = new BitmapData(source_width, source_height, false, 0xffffff);
         canvas.bitmapData.draw(picture_container, matrix);
         // test, let you see canvas working...
         //         canvas.x = -canvas.width / 2;
         //         canvas.y = -canvas.height / 2;
         //         tv_effx.visible = false;
         
         // draw the effect
         tv_effx.update();
      }
      
      private function get source_width():Number 
      {
         return sw / 3;
      }
      
      private function get source_height():Number 
      {
         return sh / 3;
      }
      
      // --------------------- LINE ---------------------
      
      private function resizeAllPictures(e:Event):void
      {
         trace('home | resizeAllPictures');
         
         // stop rendering
         tv_effx.removeEventListener(Event.ENTER_FRAME, updateTV_Effx);
         
         // resume rendering
         createTV_Effx();
         //         for (var i:int = 0; i < pictures.length; i++) 
         //         {
         //            var pic:DisplayObject = pictures[i];
         //            
         //            TweenMax.killTweensOf(pic);
         //            MyUtils.scaleToFillArea(pic, sw, sh);
         //         }
         //         // resume the tween
         //         TweenMax.to(pictures[pno], 1, { alpha:1 } );
         //         TweenMax.to(pictures[pno], 4, { width:'+50', height:'+50', ease:Linear.easeNone, onComplete:showNextPicture } );
      }
      
      private function onStageResize(e:Event = null)
      {
         x = orgX;
         y = orgY;
      }
      
      // Original x,y-pos
      private function get orgX():Number { return sw / 2; }
      private function get orgY():Number { return sh / 2; }
      
      private function get sw():Number { return stage.stageWidth; }
      private function get sh():Number { return stage.stageHeight; }
      
      // --------------------- LINE ---------------------
      
   }
   
}
